package com.lyn.solitude.host_ui.fragment

import android.Manifest
import android.app.AlertDialog
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Process
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import com.lyn.solitude.api.PluginListenerAidl
import com.lyn.solitude.host_ui.R
import com.lyn.solitude.host_ui.adapter.PluginAdapter
import com.lyn.solitude.host_ui.adapter.PluginAdapter.EmptyPluginListener
import com.lyn.solitude.host_ui.adapter.PluginAdapter.PluginViewHolder
import com.lyn.solitude.host_ui.databinding.FragmentPluginHostBinding
import com.lyn.solitude.pluginhost.PluginManager
import com.lyn.solitude.pluginhost.liveData.LiveDataManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext


/**
 * 插件宿主fragment
 *
 * @author longyn 2024/05/11
 * @version 1.0.0
 */
class PluginHostFragment : Fragment() {
    private val handler = Handler(Looper.getMainLooper())
    private lateinit var binding: FragmentPluginHostBinding
    private val pluginAdapter = PluginAdapter()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentPluginHostBinding.inflate(inflater,container,false)
        initView()
        return binding.getRoot()
    }

    private fun initView() {

        LiveDataManager.address.observe(viewLifecycleOwner
        ) { value ->
            if (TextUtils.isEmpty(value)) {
                binding.hostAddress.text = ""
            } else {
                binding.hostAddress.text = value
            }
        }
        pluginAdapter.setEmptyPluginListener(object : EmptyPluginListener {
            override fun onEmpty() {
                val gridLayoutManager = binding.pluginRecycler.layoutManager as GridLayoutManager?
                gridLayoutManager?.setSpanCount(1)
            }

            override fun onNotEmpty() {
                val gridLayoutManager = binding.pluginRecycler.layoutManager as GridLayoutManager?
                gridLayoutManager?.setSpanCount(4)
            }
        })
        if (ContextCompat.checkSelfPermission(
                requireContext(),
                Manifest.permission.READ_EXTERNAL_STORAGE
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(
                requireActivity(),
                arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
                1
            )
        }
        binding.pluginRecycler.setAdapter(pluginAdapter)
        pluginAdapter.setOnItemClickListener(object : PluginAdapter.OnItemClickListener {
            override fun onItemClick(holder: PluginViewHolder?, position: Int) {
                pluginAdapter.getItem(position)?.let { plugin ->
                    PluginManager.open(plugin.id)
                }
            }
        })
        pluginAdapter.setOnItemLongClickListener(object : PluginAdapter.OnItemLongClickListener {
            override fun onItemLongClick(holder: PluginViewHolder?, position: Int): Boolean {
                pluginAdapter.getItem(position)?.let { plugin ->
                    AlertDialog.Builder(requireContext()).setTitle(getString(R.string.hint))
                        .setMessage(getString(R.string.are_you_sure_you_want_to_uninstall_this_plugin))
                        .setNegativeButton(getString(R.string.cancel)) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
                        .setPositiveButton(getString(R.string.confirm)) { dialog: DialogInterface, _: Int ->
                            dialog.dismiss()
                            Thread {
                                val remove: Boolean = PluginManager.uninstall(plugin.id)
                                handler.post {
                                    if (remove) {
                                        pluginAdapter.remove(position)
                                        Toast.makeText(
                                            requireContext(),
                                            getString(R.string.uninstall_successfully),
                                            Toast.LENGTH_SHORT
                                        ).show()
                                    } else {
                                        Toast.makeText(
                                            requireContext(),
                                            getString(R.string.uninstallation_failure),
                                            Toast.LENGTH_SHORT
                                        ).show()
                                    }
                                }
                            }.start()
                        }.setCancelable(false).show()
                }
                return true
            }
        })
        PluginManager.setPluginListener(object : PluginListenerAidl.Stub() {
            override fun onListenerInitialize(pid: Int) {
                refreshData()
            }

            override fun onInstall(success: Boolean, path: String?, msg: String?, pid: Int) {
                if (success) {
                    Process.killProcess(pid)
                    lifecycleScope.launch(Dispatchers.Main) {
                        Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()
                        withContext(Dispatchers.Default) {
                            val plugins = PluginManager.getAllPlugin()
                            withContext(Dispatchers.Main) {
                                pluginAdapter.setPluginData(plugins)
                            }
                        }
                    }
                }
            }

            override fun onUnInstall(
                success: Boolean,
                id: Long,
                path: String?,
                msg: String?,
                pid: Int
            ) {
                if (success) {
                    Process.killProcess(pid)
                    lifecycleScope.launch(Dispatchers.Main) {
                        Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()
                    }
                }
            }

            override fun onOpen(success: Boolean, id: Long, path: String?, msg: String?, pid: Int) {

            }

            override fun onJump(
                success: Boolean,
                id: Long,
                className: String?,
                msg: String?,
                pid: Int
            ) {

            }
        })
    }

    private fun refreshData() {
        lifecycleScope.launch(Dispatchers.Default) {
            val plugins = PluginManager.getAllPlugin()
            withContext(Dispatchers.Main) {
                pluginAdapter.setPluginData(plugins)
            }
        }
    }

    companion object {
        private const val TAG = "PluginHostFragment"
    }
}
